package ${package}.controller.user;


import cn.hutool.core.lang.tree.Tree;
import cn.tannn.jdevelops.annotations.web.authentication.ApiPlatform;
import cn.tannn.jdevelops.annotations.web.constant.PlatformConstant;
import cn.tannn.jdevelops.annotations.web.mapping.PathRestController;
import cn.tannn.jdevelops.exception.built.BusinessException;
import cn.tannn.jdevelops.jpa.result.JpaPageResult;
import ${package}.customer.constant.MenuStatus;
import ${package}.customer.constant.MenuType;
import ${package}.controller.user.dto.MenuAdd;
import ${package}.controller.user.dto.MenuAlter;
import ${package}.util.TreeUtil;
import ${package}.customer.entity.Menu;
import ${package}.customer.service.MenuService;
import ${package}.controller.user.dto.MenuPage;
import ${package}.controller.user.vo.MenuVO;

import cn.tannn.jdevelops.result.response.ResultPageVO;
import cn.tannn.jdevelops.result.response.ResultVO;
import cn.tannn.jdevelops.result.utils.ListTo;
import cn.tannn.jdevelops.result.utils.UUIDUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import jakarta.validation.Valid;
import java.util.List;

/**
 * 菜单
 *
 * @author <a href="https://tannn.cn/">tan</a>
 * @date 2023/12/4 13:19
 */
@PathRestController("/menu")
@Tag(name = "菜单管理")
@Slf4j
@RequiredArgsConstructor
@ApiPlatform(platform = PlatformConstant.WEB_ADMIN)
public class MenuController {

    private final MenuService menuService;


    @PostMapping("add")
    @Operation(summary = "新增菜单路由")
    public ResultVO<MenuVO> addMenu(@RequestBody @Valid MenuAdd add) {
        if (StringUtils.isBlank(add.getCode())) {
            add.setCode(UUIDUtils.getInstance().generateShortUuid());
        }
        // 验证同级名称重复
        menuService.verifyName(add.getName(), add.getParentCode(), null);
        Menu addMenu = add.to(Menu.class);

        // 验证父节点是否有效  - 且启用中 (返回值用来修改父级名)
        menuService.verifyParentExist(add.getParentCode()).ifPresent(parent -> addMenu.setParentName(parent.getName()));
        Menu menuSave = menuService.saveOne(addMenu);
        return ResultVO.success("新增成功", menuSave.to(MenuVO.class));
    }


    @PostMapping("alter")
    @Operation(summary = "修改菜单路由")
    public ResultVO<String> alterMenu(@RequestBody @Valid MenuAlter alter) {
        Menu menu = menuService.findByCode(alter.getCode())
                .orElseThrow(() -> new BusinessException("当前功能节点不存在，请重新选择"));
        menu.alterMenuToMenu(alter);
        if (alter.getParentCode() != null) {
            // 验证父节点是否有效 - 且启用中 (返回值用来修改父级名)
            menuService.verifyParentExist(alter.getParentCode()).ifPresent(parent -> menu.setParentName(parent.getName()));
            if (StringUtils.isNotBlank(alter.getName())) {
                // 验证同级名称重复
                menuService.verifyName(alter.getName(), alter.getParentCode(), alter.getCode());
            }
        }
        if (StringUtils.isNotBlank(alter.getName()) && alter.getParentCode() == null) {
            throw new BusinessException("修改名称时，必须要传入父级ID，如果改为顶级则传0");
        }
        menuService.saveOne(menu);
        return ResultVO.successMessage("修改成功");
    }


    @GetMapping("getChild")
    @Operation(summary = "根据code获取下一级的子节点(默认所有)")
    @Parameter(description = "节点编码", name = "code", required = true)
    @Parameter(description = "节点状态（0、禁用；1、启用） 不传默认查所有", name = "status")
    @Parameter(description = "类型（0、节点；1、功能；2、按钮） 不传默认查所有", name = "type")
    public ResultVO<List<MenuVO>> getChild(final String code,
                                           final Integer status,
                                           final Integer type) {
        List<Menu> child = menuService.getChild(code, MenuStatus.fromValue(status), MenuType.fromValue(type));
        return ResultVO.success("查询成功", ListTo.to(MenuVO.class, child));
    }


    @PostMapping("delete")
    @Operation(summary = "删除菜单(同时删除其全部子级)")
    public ResultVO<String> deleteMenu(@RequestBody List<String> codes) {
        menuService.deleteMenu(codes);
        return ResultVO.successMessage("删除成功");
    }

    @PostMapping("select")
    @Operation(summary = "模糊查询且分页(单级数据)")
    public ResultPageVO<MenuVO, JpaPageResult<MenuVO>> selectMenu(@RequestBody @Valid MenuPage select) {
        Page<Menu> menus = menuService.findPage(select, select.getPage());
        JpaPageResult<MenuVO> pageResult = JpaPageResult.toPage(menus, MenuVO.class);
        return ResultPageVO.success(pageResult, "查询成功");
    }


    @PostMapping("disable")
    @Operation(summary = "菜单禁用(注意禁用会让子菜单也跟着禁用)")
    public ResultVO<String> disable(@RequestBody List<String> codes) {
        menuService.disable(codes);
        return ResultVO.successMessage("禁用成功");
    }


    @PostMapping("enabled")
    @Operation(summary = "菜单启用(注意启用会让父菜单跟着启用)")
    public ResultVO<String> enabled(@RequestBody List<String> codes) {
        menuService.enabled(codes);
        return ResultVO.successMessage("启用成功");
    }


    @PostMapping("tree")
    @Operation(summary = "菜单树")
    public ResultVO<List<Tree<String>>> menuTree() {
        List<Menu> allExDisabled = menuService.getAllExDisabled();
        List<Tree<String>> treeNodes = TreeUtil.menusTree(allExDisabled);
        return ResultVO.success("查询成功", treeNodes);
    }

}
